package com.totoro.tygeneratedragonblock.listener;

import com.totoro.tygeneratedragonblock.TyGenerateDragonBlock;
import com.totoro.tygeneratedragonblock.constants.StaticSystemVarConst;
import com.totoro.tygeneratedragonblock.data.ChunkCoordinate;
import com.totoro.tygeneratedragonblock.data.ComputeResult;
import com.totoro.tygeneratedragonblock.data.ConditionResult;
import com.totoro.tygeneratedragonblock.enums.*;
import com.totoro.tygeneratedragonblock.executor.action.ActionExecutor;
import com.totoro.tygeneratedragonblock.executor.condition.ConditionExecutor;
import com.totoro.tygeneratedragonblock.manager.LoggerManager;
import com.totoro.tygeneratedragonblock.pojo.BlockDefinition;
import com.totoro.tygeneratedragonblock.pojo.SpawnPoint;
import com.totoro.tygeneratedragonblock.utils.ColorUtil;
import com.totoro.tygeneratedragonblock.utils.StrUtil;
import eu.decentsoftware.holograms.api.DHAPI;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Totoro
 * @version 0.1.0
 * @date 2025/8/10 - 19:12
 * @description 方块监听类
 **/
public class BlockListener implements Listener {

    private final TyGenerateDragonBlock plugin;

    private final LoggerManager logger;

    public BlockListener(TyGenerateDragonBlock plugin) {
        this.plugin = plugin;
        this.logger = plugin.getLoggerManager();
    }

    @EventHandler
    public void onChunkLoad(ChunkLoadEvent event) {
        String worldName = event.getWorld().getName();
        if (!plugin.getSpawnersManager().getTargetWorlds().contains(worldName)) {
            return;
        }

        ChunkCoordinate chunkCoordinate = new ChunkCoordinate(event.getChunk());
        Set<String> spawnIds = plugin.getChunkMappingManager().getChunkSpawnMap().get(chunkCoordinate);
        if (spawnIds != null) {
            for (String spawnId : spawnIds) {
                SpawnPoint spawn = plugin.getSpawnersManager().getSpawnPoints().get(spawnId);
                if (spawn != null) {
                    // 只生成未激活的
                    if (!plugin.getSpawnersManager().getLocationToSpawnId().containsKey(spawn.getLocation())) {
                        plugin.getSpawnersManager().placeSpawnBlock(spawn);
                    }
                }
            }
        }
    }


    @EventHandler
    public void onBlockBreak(BlockBreakEvent event) {
        if(event.getBlock().getType() != Material.SKULL) {
            return;
        }
        Location location = event.getBlock().getLocation();
        logger.debug("当前方块坐标：" + location.toString());
        String spawnId = plugin.getSpawnersManager().getLocationToSpawnId().get(location);
        logger.debug("方块对应的spawnId：" + spawnId);

        if (spawnId != null) {
            SpawnPoint spawn = plugin.getSpawnersManager().getSpawnPoints().get(spawnId);
            logger.debug("方块对应的spawn：" + (spawn == null));
            if (spawn != null) {
                BlockDefinition blockDef = plugin.getBlocksManager().getBlockDefinitions().get(spawn.getBlockId());
                logger.debug("方块对应的blockDef：" + (blockDef == null));
                if (blockDef != null) {
                    Player player = event.getPlayer();
                    // 取消破坏事件，因为下面是将物品设置为空气
                    event.setCancelled(true);

                    // 检查，获取当前手中物品
                    ItemStack handItem = player.getInventory().getItemInMainHand();
                    if(handItem == null || handItem.getType() == Material.AIR) {
                        return;
                    }

                    // 检查物品名称
                    // 物品名称先用全局的，再判断这个方块是否写了匹配的物品名称
                    List<String> itemMatch = plugin.getConfigManager().getConfig().getItemMatch();
                    logger.debug(blockDef.getItemMatch().toString() +"：当前矿物物品判断");
                    if(blockDef.getItemMatch() != null && !blockDef.getItemMatch().isEmpty()) {
                        itemMatch = blockDef.getItemMatch();
                    }
                    if(! handItem.hasItemMeta() || ! handItem.getItemMeta().hasDisplayName()) {
                        player.sendMessage(plugin.getConfigManager().getConfig().getPrefix() + ColorUtil.color("&c你没有使用正确的物品进行挖掘！"));
                        return;
                    }
                    boolean isMatchItem = false;
                    for (String match : itemMatch) {
                        ItemMatchEnum itemMatchEnum = ItemMatchEnum.getItemMatchEnum(match);
                        logger.debug("匹配方式：" + itemMatchEnum.getMatchType());
                        logger.debug("匹配关键字：" + match);
                        logger.debug("物品名称：" + handItem.getItemMeta().getDisplayName());
                        Boolean execute = itemMatchEnum.getItemMatchExecutor().execute(handItem.getItemMeta().getDisplayName(), match);
                        logger.debug("匹配结果：" + execute);
                        if(execute) {
                            isMatchItem = true;
                            break;
                        }
                    }
                    if(!isMatchItem) {
                        event.setCancelled(true);
                        player.sendMessage(plugin.getConfigManager().getConfig().getPrefix() + ColorUtil.color("&c你没有使用正确的物品进行挖掘！"));
                        return;
                    }

                    // 判断是否有权限，如果有权限就判断
                    if(blockDef.getCondition() != null && !blockDef.getCondition().isEmpty()) {
                        // 判断condition变量条件
                        boolean conditionFlag = true;
                        // 失败原因
                        String fallReason = null;
                        List<String> condition = blockDef.getCondition();
                        for (String cdt : condition) {
                            ConditionExecutor conditionExecutor = ConditionEnum.getExecutor(cdt);
                            ConditionResult conditionResult = conditionExecutor.execute(cdt, player);
                            if(! conditionResult.getIsSuccess()) {
                                conditionFlag = false;
                                fallReason = conditionResult.getFailReason();
                                break;
                            }
                        }
                        if(!conditionFlag) {
                            event.setCancelled(true);
                            if(null != fallReason) {
                                player.sendMessage(fallReason);
                            } else {
                                player.sendMessage(plugin.getConfigManager().getConfig().getPrefix() + ColorUtil.color("&c你没有权限进行挖掘！"));
                            }
                            return;
                        }
                    }

                    // 移除方块
                    event.getBlock().setType(Material.AIR);
                    // 如果加载了悬浮字依赖，尝试删除，因为config的配置可能修改，所以这里尝试删除悬浮字
                    if (StaticSystemVarConst.dependentDecentHologramsEnable) {
                        if(null != DHAPI.getHologram(StrUtil.toUniqueEnglish(spawn.getId()))) {
                            DHAPI.removeHologram(StrUtil.toUniqueEnglish(spawn.getId()));
                        }
                    }
                    plugin.getSpawnersManager().getLocationToSpawnId().remove(location);

                    // 解析本次玩家对于该方块的valueSet
                    Map<String, ComputeResult> parseValueMap = getStringComputeResultMap(blockDef, player);
                    // 执行方块掉落，如果有
                    if(null != blockDef.getDrops() && !blockDef.getDrops().isEmpty()) {
                        for (String drop : blockDef.getDrops()) {
                            DropExecutorEnum dropExecutorEnum = DropExecutorEnum.getDropExecutorEnum(drop);
                            if(null != dropExecutorEnum) {
                                dropExecutorEnum.getDropExecutor().execute(parseValueMap, player, drop, location);
                            }
                        }
                    }

                    // 执行经验掉落，如果有
                    if(null != blockDef.getExp()) {
                        // 判断经验是否能直接比对valueSet
                        int exp = 0;
                        if(parseValueMap.containsKey(blockDef.getExp())) {
                            // 成功，获取结果值转成Double再四舍五入成int
                            exp = (int) Math.round(parseValueMap.get(blockDef.getExp()).getResult().doubleValue());
                        } else {
                            // 失败，那就用原来的
                            exp = Math.toIntExact(Math.round(Double.parseDouble(blockDef.getExp())));
                        }
                        // 生成经验求
                        World world = location.getWorld();
                        // 在指定位置生成经验球，参数为经验值数量
                        ExperienceOrb orb = world.spawn(location, ExperienceOrb.class);
                        // 设置经验球的经验值
                        orb.setExperience(exp);
                    }

                    // 执行动作组，如果有
                    List<String> actions = blockDef.getActions();
                    if(null != actions && !actions.isEmpty()) {
                        for (String action : actions) {
                            // 获取该执行对应的接口
                            ActionExecutor actionExecutor = ActionEnum.getExecutor(action);
                            actionExecutor.execute(parseValueMap, action, player);
                        }
                    }

                    // 启动重生任务
                    BukkitRunnable task = new BukkitRunnable() {
                        @Override
                        public void run() {
                            plugin.getSpawnersManager().placeSpawnBlock(spawn);
                            plugin.getRespawnTasksManager().remove(location);
                        }
                    };
                    task.runTaskLater(plugin, Math.round(spawn.getCooldown() * 20L)); // 转换为tick
                    plugin.getRespawnTasksManager().put(location, task);
                }
            }
        }
    }

    /**
     * @author totoro
     * @description 解析方块上的定义变量valueSet
     * @date  0:51
     * @param blockDef player
     * @return java.util.Map<java.lang.String,com.totoro.tygeneratedragonblock.data.ComputeResult>
     **/
    @NotNull
    private Map<String, ComputeResult> getStringComputeResultMap(BlockDefinition blockDef, Player player) {
        Map<String, String> valueSet = blockDef.getValueSet();
        // 存放本次玩家对于该方块的解析结果Map
        Map<String, ComputeResult> parseValueMap = new HashMap<>();
        logger.debug("方块定义变量valueSet：" + valueSet.toString());
        for (Map.Entry<String, String> entry : valueSet.entrySet()) {
            String key = entry.getKey();
            String computeText = entry.getValue();
            // 使用value进行解析
            ComputeExecutorEnum computeExecutorEnum = ComputeExecutorEnum.getComputeExecutorEnum(computeText);
            ComputeResult computeResult = computeExecutorEnum.getComputeParseExecutor().execute(player, computeText);
            parseValueMap.put(key, computeResult);
        }
        return parseValueMap;
    }

}
